home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Programming / fpc / compiler / scanner.pas < prev    next >
Pascal/Delphi Source File  |  1998-09-24  |  83KB  |  2,355 lines

  1. {
  2.     $Id: scanner.pas,v 1.3 1998/03/29 17:27:59 florian Exp $
  3.     Copyright (c) 1993,97 by Florian Klaempfl
  4.  
  5.     This unit implements the scanner part and handling of the switches
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  ****************************************************************************
  22. }
  23. unit scanner;
  24.  
  25.   interface
  26.  
  27.     uses
  28.        strings,dos,cobjects,globals,symtable,systems,files,verbose,link;
  29.  
  30.     const
  31.        id_len = 14;
  32.  
  33.     type
  34.        ident = string[id_len];
  35.  
  36.     const
  37. {$ifdef L_C}
  38.        anz_keywords = 32;
  39.  
  40.        keyword : array[1..anz_keywords] of ident = (
  41.           'auto','break','case','char','const','continue','default','do',
  42.           'double','else','enum','extern','float','for','goto','if',
  43.           'int','long','register','return','short','signed','sizeof','static',
  44.           'struct','switch','typedef','union','unsigned','void','volatile',
  45.           'while');
  46. {$else}
  47.        anz_keywords = 71;
  48.  
  49.        keyword : array[1..anz_keywords] of ident = (
  50. {                'ABSOLUTE',}
  51.                  'AND',
  52.                  'ARRAY','AS','ASM',
  53. {                'ASSEMBLER',}
  54.                  'BEGIN',
  55.                  'BREAK','CASE','CLASS',
  56.                  'CONST','CONSTRUCTOR','CONTINUE',
  57.                  'DESTRUCTOR','DISPOSE','DIV','DO','DOWNTO','ELSE','END',
  58.                  'EXCEPT',
  59.                  'EXIT',
  60. {                'EXPORT',}
  61.                  'EXPORTS',
  62. {                'EXTERNAL',}
  63.                  'FAIL','FALSE',
  64. {                'FAR',}
  65.                  'FILE','FINALLY','FOR',
  66. {                'FORWARD',}
  67.                  'FUNCTION','GOTO','IF','IMPLEMENTATION','IN',
  68.                  'INHERITED','INITIALIZATION',
  69. {                'INLINE',} {INLINE is a reserved word in TP. Why?}
  70.                  'INTERFACE',
  71. {                'INTERRUPT',}
  72.                  'IS',
  73.                  'LABEL','LIBRARY','MOD',
  74. {                'NEAR',}
  75.                  'NEW','NIL','NOT','OBJECT',
  76.                  'OF','ON','OPERATOR','OR','OTHERWISE','PACKED',
  77.                  'PROCEDURE','PROGRAM','PROPERTY',
  78.                  'RAISE','RECORD','REPEAT','SELF',
  79.                  'SET','SHL','SHR','STRING','THEN','TO',
  80.                  'TRUE','TRY','TYPE','UNIT','UNTIL',
  81.                  'USES','VAR',
  82. {                'VIRTUAL',}
  83.                  'WHILE','WITH','XOR');
  84. {***}
  85.  
  86.        keyword_token : array[1..anz_keywords] of ttoken = (
  87. {                _ABSOLUTE,}
  88.                  _AND,
  89.                  _ARRAY,_AS,_ASM,
  90. {                _ASSEMBLER,}
  91.                  _BEGIN,
  92.                  _BREAK,_CASE,_CLASS,
  93.                  _CONST,_CONSTRUCTOR,_CONTINUE,
  94.                  _DESTRUCTOR,_DISPOSE,_DIV,_DO,_DOWNTO,
  95.                  _ELSE,_END,_EXCEPT,
  96.                  _EXIT,
  97. {                _EXPORT,}
  98.                  _EXPORTS,
  99. {                _EXTERNAL,}
  100.                  _FAIL,_FALSE,
  101. {                _FAR,}
  102.                  _FILE,_FINALLY,_FOR,
  103. {                _FORWARD,}
  104.                  _FUNCTION,_GOTO,_IF,_IMPLEMENTATION,_IN,
  105.                  _INHERITED,_INITIALIZATION,
  106. {                _INLINE,}
  107.                  _INTERFACE,
  108. {                _INTERRUPT,}
  109.                  _IS,
  110.                  _LABEL,_LIBRARY,_MOD,
  111. {                _NEAR,}
  112.                  _NEW,_NIL,_NOT,_OBJECT,
  113.                  _OF,_ON,_OPERATOR,_OR,_OTHERWISE,_PACKED,
  114.                  _PROCEDURE,_PROGRAM,_PROPERTY,
  115.                  _RAISE,_RECORD,_REPEAT,_SELF,
  116.                  _SET,_SHL,_SHR,_STRING,_THEN,_TO,
  117.                  _TRUE,_TRY,_TYPE,_UNIT,_UNTIL,
  118.                  _USES,_VAR,
  119. {                _VIRTUAL,}
  120.                  _WHILE,_WITH,_XOR);
  121. {$endif}
  122.  
  123.     function yylex : ttoken;
  124.     procedure initscanner(const fn: string);
  125.     procedure donescanner(compiled_at_higher_level : boolean);
  126.  
  127.     { the asm parser use this function getting the input }
  128.     function asmgetchar : char;
  129.  
  130.     { this procedure is called at the end of each line }
  131.     { and the function does the statistics }
  132.     procedure write_line;
  133.     { this procedure must be called before starting another scanner }
  134.     procedure update_line;
  135.  
  136.     type
  137.        tpreproctoken = (PP_IFDEF,PP_IFNDEF,PP_ELSE,PP_ENDIF,PP_IFOPT);
  138.  
  139.        ppreprocstack = ^tpreprocstack;
  140.  
  141.        tpreprocstack = object
  142.           t : tpreproctoken;
  143.           accept : boolean;
  144.           next : ppreprocstack;
  145.           name : string;
  146.           line_nb : longint;
  147.           constructor init(_t : tpreproctoken;a : boolean;n : ppreprocstack);
  148.           destructor done;
  149.        end;
  150.  
  151.     var
  152.        pattern,orgpattern : string;
  153.        { true, if type declarations are parsed }
  154.        parse_types : boolean;
  155.  
  156.     { macros }
  157.  
  158.     const
  159. {$ifdef TP}
  160.        maxmacrolen = 1024;
  161. {$else}
  162.        maxmacrolen = 16*1024;
  163. {$endif}
  164.  
  165.     type
  166.        tmacrobuffer = array[0..maxmacrolen-1] of char;
  167.  
  168.     var
  169.        macropos : longint;
  170.        macrobuffer : ^tmacrobuffer;
  171.        preprocstack : ppreprocstack;
  172.        inputbuffer : pchar;
  173.        inputpointer : word;
  174.        s_point : boolean;
  175.        c : char;
  176.        comment_level : word;
  177. {this is usefull to get the write filename
  178. for the last instruction of an include file !}
  179.        Const        FileHasChanged : Boolean = False;
  180.  
  181.   implementation
  182.  
  183.     const
  184.        newline = #10;
  185.  
  186.     { const
  187.        line_count : longint = 0; stored in tinputfile }
  188.  
  189.     { used to get better line info }
  190.     procedure update_line;
  191.  
  192.       begin
  193.          inc(current_module^.current_inputfile^.line_no,
  194.            current_module^.current_inputfile^.line_count);
  195.          current_module^.current_inputfile^.line_count:=0;
  196.       end;
  197.  
  198.     procedure reload;
  199.  
  200.       var
  201.          readsize : word;
  202.          i,saveline,count : longint;
  203.  
  204.       begin
  205.          if filehaschanged then
  206.            begin
  207. {$ifdef EXTDEBUG}
  208.               writeln ('Note: Finished reading ',current_module^.current_inputfile^.name^);
  209.               write  (' Coming back to ');
  210.               current_module^.current_inputfile^.next^.write_file_line(output);
  211.               writeln;
  212. {$endif EXTDEBUG}
  213.               current_module^.current_inputfile:=current_module^.current_inputfile^.next;
  214.  
  215.               { this was missing !}
  216.               c:=inputbuffer[inputpointer];
  217.               inc(inputpointer);
  218. {$ifdef EXTDEBUG}
  219.               write('Next 16 char "');
  220.               for i:=-1 to 14 do
  221.                 write(inputbuffer[inputpointer+i]);
  222.               writeln('"');
  223. {$endif EXTDEBUG}
  224.               filehaschanged:=false;
  225.               exit;
  226.            end;
  227.          if current_module^.current_inputfile=nil then
  228.            internalerror(14);
  229.          if current_module^.current_inputfile^.filenotatend then
  230.            begin
  231.               { load the next piece of source }
  232.               blockread(current_module^.current_inputfile^.f,inputbuffer^,
  233.                 current_module^.current_inputfile^.bufsize-1,readsize);
  234.               { check if non-empty file }
  235.  
  236.               { this is an aweful hack FK }
  237.               if readsize > 0 then
  238.               begin
  239.                 { check if null character before readsize }
  240.                 { this mixed up the scanner..             }
  241.  
  242.                 { force proper line counting }
  243.                 saveline:=current_module^.current_inputfile^.line_no;
  244.                 i:=0;
  245.                 while i<readsize do
  246.                   begin
  247.                      if inputbuffer[i] in [#10,#13] then
  248.                        begin
  249.                           if (byte(inputbuffer[i+1])+byte(inputbuffer[i])=23) then
  250.                             inc(i);
  251.                           inc(current_module^.current_inputfile^.line_no);
  252.                        end;
  253.                      if inputbuffer[i] = #0 then
  254.                        Message(scan_f_illegal_char);
  255.                      inc(i);
  256.                   end;
  257.                 current_module^.current_inputfile^.line_no:=saveline;
  258.               end;
  259.  
  260.               inputbuffer[readsize]:=#0;
  261.               c:=inputbuffer[0];
  262.  
  263.               { inputpointer points always to the _next_ character to read }
  264.               inputpointer:=1;
  265.               if eof(current_module^.current_inputfile^.f) then
  266.                 begin
  267.                    current_module^.current_inputfile^.filenotatend:=false;
  268.  
  269.                    { if this is the main source file then EOF }
  270.                    if current_module^.current_inputfile^.next=nil then
  271.                      inputbuffer[readsize]:=#26;
  272.                 end;
  273.            end
  274.          else
  275.            begin
  276.               current_module^.current_inputfile^.close;
  277.               inputbuffer:=current_module^.current_inputfile^.next^.buf;
  278.               inputpointer:=current_module^.current_inputfile^.next^.bufpos;
  279.  
  280.               if assigned(current_module^.current_inputfile^.next) then
  281.                 begin
  282.                    c:=inputbuffer[inputpointer];
  283.                    filehaschanged:=True;
  284. {$ifdef EXTDEBUG}
  285.                    write('Next 16 char "');
  286.                    for i := 0 to 15 do write(inputbuffer[inputpointer+i]);
  287.                      writeln('"');
  288. {$endif}
  289.                    inputbuffer[inputpointer] := #0;
  290.                    { if c=newline writeline is called but increment the old
  291.                      inputstack instead of the new one }
  292.                    if c=newline then
  293.                      begin
  294.                         inc(current_module^.current_inputfile^.next^.line_no);
  295.                         dec(current_module^.current_inputfile^.line_no);
  296.                      end;
  297.                 end;
  298.             end;
  299.       end;
  300.  
  301.  
  302.     procedure write_line;
  303.  
  304.       var
  305.          status : tcompilestatus;
  306.  
  307.       begin
  308. {$ifdef ver0_6}
  309.          status.totalcompiledlines:=abslines;
  310.          status.currentline:=current_module^.current_inputfile^.line_no
  311.            +current_module^.current_inputfile^.line_count;
  312.          status.currentsource:=current_module^.current_inputfile^.name^+current_module^.current_inputfile^.ext^;
  313.          status.totallines:=0;
  314. {$else}
  315.          with status do
  316.            begin
  317.               totalcompiledlines:=abslines;
  318.               currentline:=current_module^.current_inputfile^.line_no
  319.                 +current_module^.current_inputfile^.line_count;
  320.               currentsource:=current_module^.current_inputfile^.name^+current_module^.current_inputfile^.ext^;
  321.               totallines:=0;
  322.            end;
  323. {$endif}
  324.          if compilestatusproc(status) then
  325.           stop;
  326.          inc(current_module^.current_inputfile^.line_count);
  327.          lastlinepointer:=inputpointer;
  328.          inc(abslines);
  329.       end;
  330.  
  331.     procedure src_comment;forward;
  332.  
  333.  
  334.     procedure nextchar;
  335.       begin
  336.         c:=inputbuffer[inputpointer];
  337.         inc(inputpointer);
  338.         if c=#0 then
  339.          reload;
  340.         if c in [#10,#13] then
  341.          begin
  342.            if (byte(inputbuffer[inputpointer])+byte(c)=23) then
  343.             inc(inputpointer);
  344.            write_line;
  345.            c:=newline;
  346.          end;
  347.       end;
  348.  
  349.  
  350.     procedure skipspace;
  351.       var
  352.         lastc : byte;
  353.       begin
  354.          lastc:=0;
  355.          while c in [' ',#9,#10,#12,#13] do
  356.            begin
  357.              nextchar;
  358.              if c='{' then
  359.               src_comment;
  360.            end;
  361.       end;
  362.  
  363.  
  364.     function is_keyword(var token : ttoken) : boolean;
  365.  
  366.       var
  367.          m,n,k : integer;
  368.  
  369.       begin
  370.          { there are no keywords with a length less than 2 }
  371.          if length(pattern)<=1 then
  372.            begin
  373.               is_keyword:=false;
  374.               exit;
  375.            end;
  376.  
  377.          m:=1;
  378.          n:=anz_keywords;
  379.          while m<=n do
  380.            begin
  381.               k:=m+(n-m) shr 1;
  382.               if pattern=keyword[k] then
  383.                 begin
  384.                    token:=keyword_token[k];
  385.                    is_keyword:=true;
  386.                    exit;
  387.                 end
  388.               else if pattern>keyword[k] then m:=k+1 else n:=k-1;
  389.           end;
  390.         is_keyword:=false;
  391.      end;
  392.  
  393. {*****************************************************************************
  394.                               Preprocessor
  395. *****************************************************************************}
  396.  
  397.     function readmessage:string;
  398.     var
  399.       i : longint;
  400.     begin
  401.       i:=0;
  402.       repeat
  403.         case c of
  404.          '}' : break;
  405.          #26 : Message(scan_f_end_of_file);
  406.         else
  407.           begin
  408.             if (i<255) then
  409.              begin
  410.                inc(i);
  411.                readmessage[i]:=c;
  412.              end;
  413.           end;
  414.         end;
  415.         nextchar;
  416.       until false;
  417.       readmessage[0]:=chr(i);
  418.     end;
  419.  
  420.     constructor tpreprocstack.init(_t : tpreproctoken;a : boolean;n : ppreprocstack);
  421.  
  422.       begin
  423.          t:=_t;
  424.          accept:=a;
  425.          next:=n;
  426.       end;
  427.  
  428.     destructor tpreprocstack.done;
  429.  
  430.       begin
  431.       end;
  432.  
  433.     procedure dec_comment_level;
  434.  
  435.       begin
  436.          if cs_tp_compatible in aktswitches then
  437.            comment_level:=0
  438.          else
  439.            dec(comment_level);
  440.       end;
  441.  
  442.     procedure handle_switches;
  443.  
  444.       function read_original_string : string;
  445.  
  446.         var
  447.            hs : string;
  448.  
  449.         begin
  450.            hs:='';
  451.            while c in ['A'..'Z','a'..'z','_','0'..'9'] do
  452.             begin
  453.               hs:=hs+c;
  454.               nextchar;
  455.             end;
  456.            read_original_string:=hs;
  457.         end;
  458.  
  459.       function read_string : string;
  460.  
  461.         begin
  462.            read_string:=upper(read_original_string);
  463.         end;
  464.  
  465.       function read_number : longint;
  466.  
  467.         var
  468.            hs : string;
  469.            l : longint;
  470.            w : word;
  471.  
  472.         begin
  473.            read_number:=0;
  474.            hs:='';
  475.            while c in ['0'..'9'] do
  476.              begin
  477.                 hs:=hs+c;
  478.                 nextchar;
  479.              end;
  480.            valint(hs,l,w);
  481.            read_number:=l;
  482.         end;
  483.  
  484.       var
  485.          preprocpat : string;
  486.          preproc_token : ttoken;
  487.  
  488.       function read_preproc : ttoken;
  489.  
  490. {        var
  491.            y : ttoken;
  492.            code : word;
  493.            l : longint;
  494.            hs : string;
  495.            hp : pinputfile;
  496.            hp2 : pchar;}
  497.         label
  498.            preproc_exit;
  499.  
  500.  
  501.         begin
  502.            while c in [' ',#9,#13,#12,#10] do
  503.              begin
  504. {                if c=#10 then write_line;}
  505.                 nextchar;
  506.              end;
  507.            case c of
  508.               'A'..'Z','a'..'z','_','0'..'9' :
  509.                    begin
  510.                         preprocpat:=c;
  511.                       nextchar;
  512.                       while c in ['A'..'Z','a'..'z','0'..'9','_'] do
  513.                         begin
  514.                            preprocpat:=preprocpat+c;
  515.                            nextchar;
  516.                         end;
  517.                       uppervar(preprocpat);
  518.                       read_preproc:=ID;
  519.                       goto preproc_exit;
  520.                    end;
  521.               '('      : begin
  522.                             nextchar;
  523.                             read_preproc:=LKLAMMER;
  524.                             goto preproc_exit;
  525.                          end;
  526.               ')'      : begin
  527.                             nextchar;
  528.                             read_preproc:=RKLAMMER;
  529.                             goto preproc_exit;
  530.                          end;
  531.               '+'      : begin
  532.                             nextchar;
  533.                               read_preproc:=PLUS;
  534.                             goto preproc_exit;
  535.                          end;
  536.               '-'      : begin
  537.                             nextchar;
  538.                             read_preproc:=MINUS;
  539.                             goto preproc_exit;
  540.                          end;
  541.               '*'      : begin
  542.                             nextchar;
  543.                             read_preproc:=STAR;
  544.                             goto preproc_exit;
  545.                          end;
  546.               '/'      : begin
  547.                             nextchar;
  548.                             read_preproc:=SLASH;
  549.                             goto preproc_exit;
  550.                          end;
  551.               '='      : begin
  552.                             nextchar;
  553.                             read_preproc:=EQUAL;
  554.                             goto preproc_exit;
  555.                          end;
  556.               '>'      : begin
  557.                             nextchar;
  558.                             if c='=' then
  559.                               begin
  560.                                  nextchar;
  561.                                  read_preproc:=GTE;
  562.                                  goto preproc_exit;
  563.                               end
  564.                             else
  565.                               begin
  566.                                  read_preproc:=GT;
  567.                                  goto preproc_exit;
  568.                               end;
  569.                          end;
  570.               '<'      : begin
  571.                             nextchar;
  572.                             if c='>' then
  573.                               begin
  574.                                  nextchar;
  575.                                  read_preproc:=UNEQUAL;
  576.                                  goto preproc_exit;
  577.                               end
  578.                             else if c='=' then
  579.                               begin
  580.                                  nextchar;
  581.                                  read_preproc:=LTE;
  582.                                  goto preproc_exit;
  583.                               end
  584.                             else
  585.                               begin
  586.                                  read_preproc:=LT;
  587.                                  goto preproc_exit;
  588.                               end;
  589.                          end;
  590.               #26:
  591.                 begin
  592.                    update_line;
  593.                    Message(scan_f_end_of_file);
  594.                 end
  595.               else
  596.                 begin
  597.                    read_preproc:=_EOF;
  598.                 end;
  599.            end;
  600.         preproc_exit :
  601.            update_line;
  602.         end;
  603.  
  604.       procedure preproc_consume(t : ttoken);
  605.  
  606.         begin
  607.            if t<>preproc_token then
  608.             Message(scan_e_preproc_syntax_error);
  609.            preproc_token:=read_preproc;
  610.         end;
  611.  
  612.       function read_expr : string;forward;
  613.  
  614.       function read_factor : string;
  615.  
  616.         var
  617.            hs : string;
  618.            mac : pmacrosym;
  619.            len : byte;
  620.  
  621.         begin
  622.            if preproc_token=ID then
  623.              begin
  624.                 if preprocpat='NOT' then
  625.                   begin
  626.                      preproc_consume(ID);
  627.                      hs:=read_expr;
  628.                      if hs='0' then
  629.                        read_factor:='1'
  630.                      else
  631.                        read_factor:='0';
  632.                   end
  633.                 else
  634.                   begin
  635.                      mac:=pmacrosym(macros^.search(hs));
  636.                      hs:=preprocpat;
  637.                      preproc_consume(ID);
  638.                      if assigned(mac) then
  639.                        begin
  640.                           if mac^.defined and assigned(mac^.buftext) then
  641.                             begin
  642.                                if mac^.buflen>255 then
  643.                                  begin
  644.                                     len:=255;
  645.                                     Message(scan_w_marco_cut_after_255_chars);
  646.                                  end
  647.                                else
  648.                                  len:=mac^.buflen;
  649.                                hs[0]:=char(len);
  650.                                move(mac^.buftext^,hs[1],len);
  651.                             end
  652.                           else
  653.                             read_factor:='';
  654.                        end
  655.                      else
  656.                        read_factor:=hs;
  657.                   end
  658.              end
  659.            else if preproc_token=LKLAMMER then
  660.              begin
  661.                 preproc_consume(LKLAMMER);
  662.                 read_factor:=read_expr;
  663.                 preproc_consume(RKLAMMER);
  664.              end
  665.            else
  666.              Message(scan_e_error_in_preproc_expr);
  667.         end;
  668.  
  669.       function read_term : string;
  670.  
  671.         var
  672.            hs1,hs2 : string;
  673.  
  674.         begin
  675.            hs1:=read_factor;
  676.            while true do
  677.              begin
  678.                 if (preproc_token=ID) then
  679.                   begin
  680.                      if preprocpat='AND' then
  681.                        begin
  682.                           preproc_consume(ID);
  683.                           hs2:=read_factor;
  684.                           if (hs1<>'0') and (hs2<>'0') then
  685.                             hs1:='1';
  686.                        end
  687.                      else
  688.                        break;
  689.                   end
  690.                 else
  691.                   break;
  692.              end;
  693.            read_term:=hs1;
  694.         end;
  695.  
  696.       function read_simple_expr : string;
  697.  
  698.         var
  699.            hs1,hs2 : string;
  700.  
  701.         begin
  702.            hs1:=read_term;
  703.            while true do
  704.              begin
  705.                 if (preproc_token=ID) then
  706.                   begin
  707.                      if preprocpat='OR' then
  708.                        begin
  709.                           preproc_consume(ID);
  710.                           hs2:=read_term;
  711.                           if (hs1<>'0') or (hs2<>'0') then
  712.                             hs1:='1';
  713.                        end
  714.                      else
  715.                        break;
  716.                   end
  717.                 else
  718.                   break;
  719.              end;
  720.            read_simple_expr:=hs1;
  721.         end;
  722.  
  723.       function read_expr : string;
  724.  
  725.         var
  726.            hs1,hs2 : string;
  727.            b : boolean;
  728.            t : ttoken;
  729.            w : word;
  730.            l1,l2 : longint;
  731.  
  732.         begin
  733.            hs1:=read_simple_expr;
  734.            t:=preproc_token;
  735.            if not(t in [EQUAL,UNEQUAL,LT,GT,LTE,GTE]) then
  736.              begin
  737.                 read_expr:=hs1;
  738.                 exit;
  739.              end;
  740.            preproc_consume(t);
  741.            hs2:=read_simple_expr;
  742.            if is_number(hs1) and is_number(hs2) then
  743.              begin
  744.                 valint(hs1,l1,w);
  745.                 valint(hs2,l2,w);
  746.                 case t of
  747.                    EQUAL:
  748.                      b:=l1=l2;
  749.                    UNEQUAL:
  750.                      b:=l1<>l2;
  751.                    LT:
  752.                      b:=l1<l2;
  753.                    GT:
  754.                      b:=l1>l2;
  755.                    GTE:
  756.                      b:=l1>=l2;
  757.                    LTE:
  758.                      b:=l1<=l2;
  759.                 end;
  760.              end
  761.            else
  762.              begin
  763.                 case t of
  764.                    EQUAL:
  765.                      b:=hs1=hs2;
  766.                    UNEQUAL:
  767.                      b:=hs1<>hs2;
  768.                    LT:
  769.                      b:=hs1<hs2;
  770.                    GT:
  771.                      b:=hs1>hs2;
  772.                    GTE:
  773.                      b:=hs1>=hs2;
  774.                    LTE:
  775.                      b:=hs1<=hs2;
  776.                 end;
  777.              end;
  778.            if b then
  779.              read_expr:='1'
  780.            else
  781.              read_expr:='0';
  782.        end;
  783.  
  784.     procedure skip_until_pragma;
  785.       var
  786.         found : longint;
  787.       begin
  788.          found:=0;
  789.          repeat
  790.            case c of
  791.             #26 : Message(scan_f_end_of_file);
  792.     {        newline : begin
  793.                          write_line;
  794.                          found:=0;
  795.                        end; }
  796.             '{' : begin
  797.                     if comment_level=0 then
  798.                      found:=1;
  799.                     inc(comment_level);
  800.                   end;
  801.             '}' : begin
  802.                     dec_comment_level;
  803.                     found:=0;
  804.                   end;
  805.             '$' : begin
  806.                     if found=1 then
  807.                      found:=2;
  808.                   end;
  809.            else
  810.             found:=0;
  811.            end;
  812.            nextchar;
  813.          until (found=2);
  814.          update_line;
  815.       end;
  816.  
  817.       function Is_conditional(const hs:string):boolean;
  818.       begin
  819.         Is_Conditional:=((hs='ELSE') or (hs='IFDEF') or (hs='IFNDEF') or
  820.                         (hs='IFOPT') or (hs='ENDIF') or (hs='ELSE') or (hs='IF'));
  821.       end;
  822.  
  823.       var
  824.          path,hs : string;
  825.          hp : pinputfile;
  826.          mac : pmacrosym;
  827.          found : boolean;
  828.          ht : ttoken;
  829.  
  830.       procedure popstack;
  831.  
  832.         var
  833.            hp : ppreprocstack;
  834.  
  835.         begin
  836.            hp:=preprocstack^.next;
  837.            dispose(preprocstack,done);
  838.            preprocstack:=hp;
  839.         end;
  840.  
  841.       var
  842.          _d : dirstr;
  843.          _n : namestr;
  844.          _e : extstr;
  845.          hs2,
  846.          msg : string;
  847.  
  848.       begin
  849.          nextchar;
  850.          hs:=read_string;
  851.          update_line;
  852.          Message1(scan_d_handling_switch,hs);
  853.          if hs='I' then
  854.            begin
  855.               skipspace;
  856.               hs:=c;
  857.               nextchar;
  858.               while not(c in [' ','}','*',#13,newline]) do
  859.                 begin
  860.                    hs:=hs+c;
  861.                    nextchar;
  862.                    if c=#26 then Message(scan_f_end_of_file);
  863.                 end;
  864. {              if c=newline then write_line;}
  865.               { read until end of comment }
  866.               while c<>'}' do
  867.                 begin
  868.                    nextchar;
  869.                    if c=#26 then Message(scan_f_end_of_file);
  870. {                   if c=newline then write_line;}
  871.                 end;
  872.               {
  873.               dec(comment_level);
  874.               }
  875.               { Initialization }
  876.  
  877.               if (hs[1]='-') then
  878.                 {exclude(aktswitches,cs_iocheck) Not yet supported.}
  879.                 aktswitches:=aktswitches-[cs_iocheck]
  880.               else if (hs[1]='+') then
  881.                 {include(aktswitches,cs_iocheck) Not supported yet.}
  882.                 aktswitches:=aktswitches+[cs_iocheck]
  883.               else
  884.                 begin
  885.                    fsplit(hs,_d,_n,_e);
  886.                    update_line;
  887.                    { directory where the current file is first inspected }
  888.                    path:=search(hs,current_module^.current_inputfile^.path^,found);
  889.                    if found then
  890.                      hp:=new(pinputfile,init(path+_d,_n,_e))
  891.                    else
  892.                      begin
  893.                         path:=search(hs,includesearchpath,found);
  894.                         hp:=new(pinputfile,init(path+_d,_n,_e));
  895.                      end;
  896.                    hp^.reset;
  897.                    if ioresult=0 then
  898.                      begin
  899.                         current_module^.current_inputfile^.bufpos:=inputpointer;
  900.                         hp^.next:=current_module^.current_inputfile;
  901.                         current_module^.current_inputfile:=hp;
  902.                         current_module^.sourcefiles.register_file(hp);
  903.  
  904.                         inputbuffer:=current_module^.current_inputfile^.buf;
  905.                         Message1(scan_u_start_include_file,current_module^.current_inputfile^.name^);
  906.                         reload;
  907.  
  908.                         { we have read the }
  909.                         { comment end      }
  910.                         dec_comment_level;
  911.                         { only warn for over one => incompatible with BP }
  912.                          if (comment_level>1) then
  913.                           Message1(scan_w_comment_level,tostr(comment_level));
  914.                      end
  915.                    else
  916.                      Message1(scan_f_cannot_open_includefile,_d+_n+_e);
  917.                 end;
  918.            end
  919.          { conditional compiling ? }
  920.          else if Is_Conditional(hs) then
  921.            begin
  922.               while true do
  923.                 begin
  924.                    if hs='ENDIF' then
  925.                      begin
  926.                         { we can always accept an ELSE }
  927.                         if assigned(preprocstack) then
  928.                           begin
  929.                             Message1(scan_c_endif_found,preprocstack^.name);
  930.                              if preprocstack^.t=PP_ELSE then
  931.                                popstack;
  932.                           end
  933.                         else
  934.                           Message(scan_e_endif_without_if);
  935.  
  936.                         { now pop the condition }
  937.                         if assigned(preprocstack) then
  938.                           begin
  939.                              { we only use $ifdef in the stack }
  940.                              if (preprocstack^.t=PP_IFDEF) then
  941.                                popstack
  942.                              else
  943.                                Message(scan_e_too_much_endifs);
  944.                           end
  945.                        else
  946.                           Message(scan_e_endif_without_if);
  947.                      end
  948.                    else if hs='IFDEF' then
  949.                      begin
  950.                         skipspace;
  951.                         hs:=read_string;
  952.                         mac:=pmacrosym(macros^.search(hs));
  953.                         preprocstack:=new(ppreprocstack,init(PP_IFDEF,
  954.                           { the block before must be accepted }
  955.                           { the symbole must be exist and be defined }
  956.                           (
  957.                            (preprocstack=nil) or
  958.                             preprocstack^.accept
  959.                           ) and
  960.                            assigned(mac) and
  961.                            mac^.defined,
  962.                           preprocstack));
  963.                         preprocstack^.name:=hs;
  964.                         preprocstack^.line_nb:=current_module^.current_inputfile^.line_no;
  965.                         if preprocstack^.accept then
  966.                          Message2(scan_c_ifdef_found,preprocstack^.name,'accepted')
  967.                         else
  968.                          Message2(scan_c_ifdef_found,preprocstack^.name,'rejected');
  969.                      end
  970.                    else if hs='IFOPT' then
  971.                      begin
  972.                         skipspace;
  973.                         hs:=read_string;
  974.                         { !!!! read switch state }
  975.  
  976.                         { PP_IFDEF is correct, we doesn't distinguish between }
  977.                         { ifopt and ifdef                                     }
  978.                         preprocstack:=new(ppreprocstack,init(PP_IFDEF,
  979.                           { the block before must be accepted }
  980.                           (
  981.                            (preprocstack=nil) or
  982.                             preprocstack^.accept
  983.                           ) and
  984.                           { !!!! subject to change: }
  985.                           false,
  986.                           preprocstack));
  987.                         preprocstack^.name:=hs;
  988.                         preprocstack^.line_nb:=current_module^.current_inputfile^.line_no;
  989.                         if preprocstack^.accept then
  990.                          Message2(scan_c_ifopt_found,preprocstack^.name,'accepted')
  991.                         else
  992.                          Message2(scan_c_ifopt_found,preprocstack^.name,'rejected');
  993.                      end
  994.                    else if hs='IF' then
  995.                      begin
  996.                         skipspace;
  997.                         { start preproc expression scanner }
  998.                         preproc_token:=read_preproc;
  999.                         hs:=read_expr;
  1000.  
  1001.                         { PP_IFDEF is correct, we doesn't distinguish between }
  1002.                         { if, ifopt and ifdef                                 }
  1003.                         preprocstack:=new(ppreprocstack,init(PP_IFDEF,
  1004.                           { the block before must be accepted }
  1005.                           (
  1006.                            (preprocstack=nil) or
  1007.                             preprocstack^.accept
  1008.                           ) and
  1009.                           (hs<>'0'),
  1010.                           preprocstack));
  1011.                         preprocstack^.name:=hs;
  1012.                         preprocstack^.line_nb:=current_module^.current_inputfile^.line_no;
  1013.                         if preprocstack^.accept then
  1014.                          Message2(scan_c_if_found,preprocstack^.name,'accepted')
  1015.                         else
  1016.                          Message2(scan_c_if_found,preprocstack^.name,'rejected');
  1017.                      end
  1018.                    else if hs='IFNDEF' then
  1019.                      begin
  1020.                         skipspace;
  1021.                         hs:=read_string;
  1022.                         mac:=pmacrosym(macros^.search(hs));
  1023.                         preprocstack:=new(ppreprocstack,init(PP_IFDEF,
  1024.                           { the block before must be accepted }
  1025.                           (
  1026.                            (preprocstack=nil) or
  1027.                            preprocstack^.accept
  1028.                           ) and
  1029.                            not(assigned(mac) and
  1030.                            mac^.defined),
  1031.                           preprocstack));
  1032.                         preprocstack^.name:=hs;
  1033.                         preprocstack^.line_nb:=current_module^.current_inputfile^.line_no;
  1034.                         if preprocstack^.accept then
  1035.                          Message2(scan_c_ifndef_found,preprocstack^.name,'accepted')
  1036.                         else
  1037.                          Message2(scan_c_ifndef_found,preprocstack^.name,'rejected');
  1038.                      end
  1039.                    else if hs='ELSE' then
  1040.                      begin
  1041.                         if assigned(preprocstack) then
  1042.                           begin
  1043.                              preprocstack:=new(ppreprocstack,init(PP_ELSE,
  1044.                              { invert }
  1045.                              not(preprocstack^.accept) and
  1046.                              { but only true, if only the ifdef block is }
  1047.                              { not accepted                              }
  1048.                              (
  1049.                                (preprocstack^.next=nil) or
  1050.                                (preprocstack^.next^.accept)
  1051.                              ),
  1052.                              preprocstack));
  1053.                              preprocstack^.line_nb := current_module^.current_inputfile^.line_no;
  1054.                              preprocstack^.name := preprocstack^.next^.name;
  1055.                              if preprocstack^.accept then
  1056.                               Message2(scan_c_else_found,preprocstack^.name,'accepted')
  1057.                              else
  1058.                               Message2(scan_c_else_found,preprocstack^.name,'rejected');
  1059.                           end
  1060.                         else
  1061.                           Message(scan_e_endif_without_if);
  1062.                      end
  1063.                    else if hs='IFOPT' then
  1064.                      begin
  1065.                         skipspace;
  1066.                         hs:=read_string;
  1067.                         preprocstack:=new(ppreprocstack,init(PP_IFDEF,
  1068.                           false,
  1069.                           preprocstack));
  1070.                      end;
  1071.  
  1072.                    { accept the text ? }
  1073.                    if (preprocstack=nil) or preprocstack^.accept then
  1074.                      break
  1075.                    else
  1076.                      begin
  1077.                        Message(scan_c_skipping_until);
  1078.                        repeat
  1079.                           skip_until_pragma;
  1080.                           hs:=read_string;
  1081.                        until Is_Conditional(hs);
  1082.                      end;
  1083.                 end;
  1084.            end
  1085.          else if (hs='WAIT') then
  1086.            begin
  1087.               Message(scan_i_press_enter);
  1088.               readln;
  1089.            end
  1090.          else if (hs='INFO') or (hs='MESSAGE') then
  1091.            begin
  1092.               skipspace;
  1093.               Message1(scan_i_user_defined,readmessage);
  1094.            end
  1095.          else if hs='NOTE' then
  1096.            begin
  1097.               skipspace;
  1098.               Message1(scan_n_user_defined,readmessage);
  1099.            end
  1100.          else if hs='WARNING' then
  1101.            begin
  1102.               skipspace;
  1103.               Message1(scan_w_user_defined,readmessage);
  1104.            end
  1105.          else if hs='ERROR' then
  1106.            begin
  1107.               skipspace;
  1108.               Message1(scan_e_user_defined,readmessage);
  1109.            end
  1110.          else if (hs='FATALERROR') or (hs='STOP') then
  1111.            begin
  1112.               skipspace;
  1113.               Message1(scan_f_user_defined,readmessage);
  1114.            end
  1115.          else if hs='L' then
  1116.            begin
  1117.               skipspace;
  1118.               hs:='';
  1119.               while not(c in [' ','}',#9,newline,#13]) do
  1120.                 begin
  1121.                    hs:=hs+c;
  1122.                    nextchar;
  1123.                    if c=#26 then Message(scan_f_end_of_file);
  1124.                 end;
  1125.               hs:=FixFileName(hs);
  1126.               if not path_absolute(hs) and (current_module^.current_inputfile^.path<>nil) then
  1127.                path:=search(hs,current_module^.current_inputfile^.path^+';'+objectsearchpath,found);
  1128.               Linker.AddObjectFile(path+hs);
  1129.               current_module^.linkofiles.insert(hs);
  1130.            end
  1131.          else if hs='D' then
  1132.            begin
  1133.               if current_module^.in_main then
  1134.                 Message(scan_w_switch_is_global)
  1135.               else
  1136.                 begin
  1137.                    if c='-' then
  1138.                     aktswitches:=aktswitches-[cs_debuginfo]
  1139.                    else
  1140.                     aktswitches:=aktswitches+[cs_debuginfo];
  1141.                 end;
  1142.            end
  1143.          else if hs='R' then
  1144.            begin
  1145.                if c='-' then
  1146.                 {exclude(aktswitches,cs_rangechecking) Not yet supported.}
  1147.                 aktswitches:=aktswitches-[cs_rangechecking]
  1148.                else
  1149.                 {include(aktswitches,cs_rangechecking); Not yet supported.}
  1150.                 aktswitches:=aktswitches+[cs_rangechecking];
  1151.            end
  1152.          else if hs='Q' then
  1153.            begin
  1154.                if c='-' then
  1155.                  {include(aktswitches,cs_check_overflow) Not yet supported.}
  1156.                  aktswitches:=aktswitches-[cs_check_overflow]
  1157.                else
  1158.                  {include(aktswitches,cs_check_overflow); Not yet supported.}
  1159.                  aktswitches:=aktswitches+[cs_check_overflow]
  1160.            end
  1161.          else if hs='T' then
  1162.            begin
  1163.                if c='-' then
  1164.                  aktswitches:=aktswitches-[cs_typed_addresses]
  1165.                else
  1166.                  aktswitches:=aktswitches+[cs_typed_addresses]
  1167.            end
  1168.          else if hs='V' then
  1169.            begin
  1170.                if c='-' then
  1171.                  aktswitches:=aktswitches-[cs_strict_var_strings]
  1172.                else
  1173.                  aktswitches:=aktswitches+[cs_strict_var_strings]
  1174.            end
  1175.          else if hs='F' then
  1176.            begin
  1177.                Message(scan_n_far_directive_ignored);
  1178.            end
  1179.          else if hs='S' then
  1180.            begin
  1181.               if target_info.target<>target_linux then
  1182.                 begin
  1183.                   case c of
  1184.                    '-' : aktswitches:=aktswitches-[cs_check_stack];
  1185.                    '+' : aktswitches:=aktswitches+[cs_check_stack];
  1186.                   else
  1187.                    Message(scan_w_illegal_switch);
  1188.                   end;
  1189.                 end
  1190.               else
  1191.                 begin
  1192.                    if c in ['+','-'] then
  1193.                      Message(scan_n_stack_check_global_under_linux)
  1194.                    else
  1195.                      Message(scan_w_illegal_switch);
  1196.                  end;
  1197.            end
  1198.          else if hs='E' then
  1199.            begin
  1200.               { This is a global switch which affects all units }
  1201.               if ((current_module = main_module) and (main_module^.in_main = false)) then
  1202.                 begin
  1203.                   case c of
  1204.                    '-' : aktswitches:=aktswitches-[cs_fp_emulation];
  1205.                    '+' : aktswitches:=aktswitches+[cs_fp_emulation];
  1206.                   else
  1207.                    Message(scan_w_illegal_switch);
  1208.                   end;
  1209.                 end
  1210.               else
  1211.                 Message(scan_w_switch_is_global);
  1212.            end
  1213.          else if hs='X' then
  1214.            begin
  1215.               { This is a global switch which only affects the unit/program }
  1216.               { being compiled                                              }
  1217.               if not (current_module^.in_main) then
  1218.                 begin
  1219.                   case c of
  1220.                    '-' : aktswitches:=aktswitches-[cs_extsyntax];
  1221.                    '+' : aktswitches:=aktswitches+[cs_extsyntax];
  1222.                   else
  1223.                    Message(scan_w_illegal_switch);
  1224.                   end;
  1225.                 end
  1226.               else
  1227.                Message(scan_w_switch_is_global);
  1228.            end
  1229.          else if hs='LINKLIB' then
  1230.            begin
  1231.              skipspace;
  1232.              hs:=read_original_string;
  1233.              Linker.AddLibraryFile(hs);
  1234.              current_module^.linklibfiles.insert(hs);
  1235.            end
  1236. {$ifdef i386}
  1237.          else if hs='OUTPUT_FORMAT' then
  1238.            begin
  1239.               { this is a global switch }
  1240.               if current_module^.in_main then
  1241.                Message(scan_w_switch_is_global)
  1242.               else
  1243.                 begin
  1244.                    skipspace;
  1245.                    hs:=upper(read_string);
  1246.                    if hs='NASM' then
  1247.                      current_module^.output_format:=of_nasm
  1248.                    else if hs='MASM' then
  1249.                      current_module^.output_format:=of_masm
  1250.                    else if hs='O' then
  1251.                      current_module^.output_format:=of_o
  1252.                    else if hs='OBJ' then
  1253.                      current_module^.output_format:=of_obj
  1254.                    else
  1255.                      Message(scan_w_illegal_switch);
  1256.                 end;
  1257.               { for use in globals }
  1258.               output_format:=current_module^.output_format;
  1259.            end
  1260. {$endif}
  1261. {$ifdef SUPPORT_MMX}
  1262.          else if hs='MMX' then
  1263.            begin
  1264.                if c='-' then
  1265.                  aktswitches:=aktswitches-[cs_mmx]
  1266.                else
  1267.                  aktswitches:=aktswitches+[cs_mmx];
  1268.            end
  1269.          else if hs='SATURATION' then
  1270.            begin
  1271.                if c='-' then
  1272.                  aktswitches:=aktswitches-[cs_mmx_saturation]
  1273.                else
  1274.                  aktswitches:=aktswitches+[cs_mmx_saturation];
  1275.            end
  1276. {$endif SUPPORT_MMX}
  1277.          else if hs='DEFINE' then
  1278.            begin
  1279.               skipspace;
  1280.               hs:=read_string;
  1281.               mac:=pmacrosym(macros^.search(hs));
  1282.               if not assigned(mac) then
  1283.                 begin
  1284.                    mac:=new(pmacrosym,init(hs));
  1285.                    mac^.defined:=true;
  1286.                    Message1(parser_m_macro_defined,mac^.name);
  1287.                    macros^.insert(mac);
  1288.                 end
  1289.               else
  1290.                 begin
  1291.                    Message1(parser_m_macro_defined,mac^.name);
  1292.                    mac^.defined:=true;
  1293.  
  1294.                    { delete old definition }
  1295.                    if assigned(mac^.buftext) then
  1296.                      begin
  1297.                         freemem(mac^.buftext,mac^.buflen);
  1298.                         mac^.buftext:=nil;
  1299.                      end;
  1300.                 end;
  1301.               if support_macros then
  1302.                 begin
  1303.                    { key words are never substituted }
  1304.                    hs2:=pattern;
  1305.                    pattern:=hs;
  1306.                    if is_keyword(ht) then
  1307.                     Message(scan_e_keyword_cant_be_a_macro);
  1308.                    pattern:=hs2;
  1309.  
  1310.                    skipspace;
  1311.                    { !!!!!! handle macro params, need we this? }
  1312.  
  1313.                    { may be a macro? }
  1314.                    if c=':' then
  1315.                      begin
  1316.                         nextchar;
  1317.                         if c='=' then
  1318.                           begin
  1319.                              { first char }
  1320.                              nextchar;
  1321.                              macropos:=0;
  1322.                              while (c<>'}') do
  1323.                                begin
  1324.                                   macrobuffer^[macropos]:=c;
  1325. {                                  if c=newline then write_line;}
  1326.                                   nextchar;
  1327.                                   if c=#26 then Message(scan_f_end_of_file);
  1328.  
  1329.                                   inc(macropos);
  1330.                                   if macropos>maxmacrolen then
  1331.                                    Message(scan_f_macro_buffer_overflow);
  1332.                                end;
  1333.  
  1334.                              { free buffer of macro ?}
  1335.                              if assigned(mac^.buftext) then
  1336.                                freemem(mac^.buftext,mac^.buflen);
  1337.  
  1338.                              { get new mem }
  1339.                              getmem(mac^.buftext,macropos);
  1340.                              mac^.buflen:=macropos;
  1341.  
  1342.                              { copy the text }
  1343.                              move(macrobuffer^,mac^.buftext^,macropos);
  1344.                           end;
  1345.                      end;
  1346.                 end;
  1347.            end
  1348.          else if hs='UNDEF' then
  1349.            begin
  1350.               skipspace;
  1351.               hs:=read_string;
  1352.               mac:=pmacrosym(macros^.search(hs));
  1353.               if not assigned(mac) then
  1354.                 begin
  1355.                    mac:=new(pmacrosym,init(hs));
  1356.                    Message1(parser_m_macro_undefined,mac^.name);
  1357.                    mac^.defined:=false;
  1358.                    macros^.insert(mac);
  1359.                 end
  1360.               else
  1361.                 begin
  1362.                    Message1(parser_m_macro_undefined,mac^.name);
  1363.                    mac^.defined:=false;
  1364.                    { delete old definition }
  1365.                    if assigned(mac^.buftext) then
  1366.                      begin
  1367.                         freemem(mac^.buftext,mac^.buflen);
  1368.                         mac^.buftext:=nil;
  1369.                      end;
  1370.                 end;
  1371.            end
  1372.          else if hs='PACKRECORDS' then
  1373.            begin
  1374.               skipspace;
  1375.               if upcase(c)='N' then
  1376.                 begin
  1377.                    hs:=read_string;
  1378.                    if hs='NORMAL' then
  1379.                      aktpackrecords:=2
  1380.                    else
  1381.                     Message(scan_w_only_pack_records);
  1382.                 end
  1383.               else
  1384.                 case read_number of
  1385.                    1 : aktpackrecords:=1;
  1386.                    2 : aktpackrecords:=2;
  1387.                    4 : aktpackrecords:=4;
  1388.                    else Message(scan_w_only_pack_records);
  1389.                 end;
  1390.            end
  1391. {$ifdef i386}
  1392.          else if hs='I386_INTEL' then
  1393.            aktasmmode:=I386_INTEL
  1394.          else if hs='I386_DIRECT' then
  1395.            aktasmmode:=I386_DIRECT
  1396.          else if hs='I386_ATT' then
  1397.            aktasmmode:=I386_ATT
  1398. {$endif}
  1399.          else
  1400.            begin
  1401.               Message(scan_w_illegal_switch);
  1402.            end;
  1403.       end;
  1404.  
  1405.     procedure src_comment;
  1406.  
  1407.       begin
  1408.          inc(comment_level);
  1409.          { only warn for over one => incompatible with BP }
  1410.          if (comment_level>1) then
  1411.           Message1(scan_w_comment_level,tostr(comment_level));
  1412.          nextchar;
  1413.          while true do
  1414.            begin
  1415.               { handle compiler switches }
  1416.               if (comment_level=1) and (c='$') then
  1417.                 handle_switches;
  1418.               { handle_switches can dec comment_level, }
  1419.               { if there is an include file             }
  1420.               while (c<>'}') and (comment_level>0) do
  1421.                 begin
  1422.                    if c='{' then
  1423.                      src_comment
  1424.                    else
  1425.                      begin
  1426.                         if c=#26 then Message(scan_f_end_of_file);
  1427. {                        if c=newline then write_line;}
  1428.                         nextchar;
  1429.                      end;
  1430.                 end;
  1431.               { this is needed for the include files      }
  1432.               { if there is a end of comment then read it }
  1433.               if c='}' then
  1434.                 begin
  1435.                    nextchar;
  1436.                    dec_comment_level;
  1437.                    { only warn for over one => incompatible with BP }
  1438.                    if (comment_level>1) then
  1439.                     Message1(scan_w_comment_level,tostr(comment_level));
  1440.                 end;
  1441.               { checks }{ }
  1442.               if c='{' then
  1443.                 begin
  1444.                    inc(comment_level);
  1445.                    { only warn for over one => incompatible with BP }
  1446.                    if (comment_level>1) then
  1447.                     Message1(scan_w_comment_level,tostr(comment_level));
  1448.                    nextchar;
  1449.                 end
  1450.               else
  1451.                 break;
  1452.            end;
  1453.       end;
  1454.  
  1455.     procedure delphi_comment;
  1456.       begin
  1457.         { C++/Delphi styled comment }
  1458.         inc(comment_level);
  1459.         nextchar;
  1460.         { this is currently not supported }
  1461.         if c='$' then
  1462.           Message(scan_e_wrong_styled_switch);
  1463.         while c<>newline do
  1464.           begin
  1465.              if c=#26 then Message(scan_f_end_of_file);
  1466.              nextchar;
  1467.           end;
  1468.         dec(comment_level);
  1469.       end;
  1470.  
  1471.    const
  1472.       yylexcount : longint = 0;
  1473.  
  1474.    function yylex : ttoken;
  1475.  
  1476.      var
  1477.         y : ttoken;
  1478.         code : word;
  1479.         l : longint;
  1480.         hs : string;
  1481.         mac : pmacrosym;
  1482.         hp : pinputfile;
  1483.         hp2 : pchar;
  1484.      label
  1485.         yylex_exit;
  1486.  
  1487.      begin
  1488.         { was the last character a point ? }
  1489.  
  1490.         { this code is needed because the scanner if there is a 1. found if  }
  1491.         { this is a floating point number or range like 1..3                 }
  1492.         if s_point then
  1493.           begin
  1494.              s_point:=false;
  1495.              if c='.' then
  1496.                begin
  1497.                   nextchar;
  1498.                   yylex:=POINTPOINT;
  1499.                   goto yylex_exit;
  1500.                end;
  1501.              yylex:=POINT;
  1502.              goto yylex_exit;
  1503.           end;
  1504.  
  1505.         if c='{' then src_comment;
  1506.         skipspace;
  1507.         lasttokenpos:=inputpointer-1;
  1508.         case c of
  1509.            'A'..'Z','a'..'z','_' :
  1510.                 begin
  1511.                    orgpattern:=c;
  1512.                    nextchar;
  1513.                    while c in ['A'..'Z','a'..'z','0'..'9','_'] do
  1514.                      begin
  1515.                         orgpattern:=orgpattern+c;
  1516.                         nextchar;
  1517.                      end;
  1518.                    pattern:=orgpattern;
  1519.                    uppervar(pattern);
  1520.                    if is_keyword(y) then
  1521.                      yylex:=y
  1522.                    else
  1523.                      begin
  1524.                         { this takes some time ... }
  1525.                         if support_macros then
  1526.                           begin
  1527.                              mac:=pmacrosym(macros^.search(pattern));
  1528.                              if assigned(mac) and (assigned(mac^.buftext)) then
  1529.                                begin
  1530.                                   { don't forget the last char }
  1531.                                   dec(inputpointer);
  1532.                                   current_module^.current_inputfile^.bufpos:=inputpointer;
  1533.  
  1534.                                   { this isn't a proper way, but ... }
  1535.                                   hp:=new(pinputfile,init('','Macro '+pattern,''));
  1536.  
  1537.                                   hp^.next:=current_module^.current_inputfile;
  1538.                                   current_module^.current_inputfile:=hp;
  1539.                                   current_module^.sourcefiles.register_file(hp);
  1540.  
  1541.                                   { set an own buffer }
  1542.                                   getmem(hp2,mac^.buflen+1);
  1543.                                   current_module^.current_inputfile^.setbuf(hp2,mac^.buflen+1);
  1544.  
  1545.                                   inputbuffer:=current_module^.current_inputfile^.buf;
  1546.  
  1547.                                   { copy text }
  1548.                                   move(mac^.buftext^,inputbuffer^,mac^.buflen);
  1549.  
  1550.                                   { put end sign }
  1551.                                   inputbuffer[mac^.buflen+1]:=#0;
  1552.  
  1553.                                   { load c }
  1554.                                   c:=inputbuffer[0];
  1555.  
  1556.                                   { point to the next char }
  1557.                                   inputpointer:=1;
  1558.  
  1559.                                   { handle empty macros }
  1560.                                   if c=#0 then reload;
  1561.  
  1562.                                   { play it again ... }
  1563.                                   inc(yylexcount);
  1564.                                   if yylexcount>16 then
  1565.                                     Message(scan_w_macro_deep_ten);
  1566. {$ifdef TP}
  1567.                                   yylex:=yylex;
  1568. {$else}
  1569.                                   yylex:=yylex();
  1570. {$endif}
  1571.                                 { that's all folks }
  1572.                                 dec(yylexcount);
  1573.                                 goto yylex_exit;
  1574.                               end;
  1575.                            end;
  1576.                            yylex:=ID;
  1577.                         end;
  1578.                       goto yylex_exit;
  1579.                    end;
  1580.            '$'      : begin
  1581.                          pattern:=c;
  1582.                          nextchar;
  1583.                          while ((ord(c)>=ord('0')) and (ord(c)<=ord('9'))) or
  1584.                                 (ord(upcase(c))>=ord('A')) and (ord(upcase(c))<=ord('F')) do
  1585.                            begin
  1586.                               pattern:=pattern+c;
  1587.                               nextchar;
  1588.                            end;
  1589.                          yylex:=INTCONST;
  1590.                          goto yylex_exit;
  1591.                       end;
  1592. {why ?ifdef FPC}
  1593. { because the tp val doesn't recognize this, }
  1594. { so it's useless in TP versions             }
  1595. { it's solved with valint                    }
  1596.            '%'      : begin
  1597.                          pattern:=c;
  1598.                          nextchar;
  1599.                          while c in ['0','1'] do
  1600.                            begin
  1601.                               pattern:=pattern+c;
  1602.                               nextchar;
  1603.                            end;
  1604.                          yylex:=INTCONST;
  1605.                          goto yylex_exit;
  1606.                       end;
  1607. {cond removed endif}
  1608.            '0'..'9' : begin
  1609.                          pattern:=c;
  1610.                          nextchar;
  1611.                          while c in ['0'..'9'] do
  1612.                            begin
  1613.                               pattern:=pattern+c;
  1614.                               nextchar;
  1615.                            end;
  1616.                          if c in ['.','e','E'] then
  1617.                            begin
  1618.                               if c='.' then
  1619.                                 begin
  1620.                                    nextchar;
  1621.                                    if not(c in ['0'..'9']) then
  1622.                                      begin
  1623.                                         s_point:=true;
  1624.                                         yylex:=INTCONST;
  1625.                                         goto yylex_exit;
  1626.                                      end;
  1627.                                    pattern:=pattern+'.';
  1628.                                    while c in ['0'..'9'] do
  1629.                                      begin
  1630.                                         pattern:=pattern+c;
  1631.                                         nextchar;
  1632.                                      end;
  1633.                                 end;
  1634.                               if upcase(c)='E' then
  1635.                                 begin
  1636.                                    pattern:=pattern+'E';
  1637.                                    nextchar;
  1638.                                    if c in ['-','+'] then
  1639.                                      begin
  1640.                                         pattern:=pattern+c;
  1641.                                         nextchar;
  1642.                                      end;
  1643.                                    if not(c in ['0'..'9']) then
  1644.                                      Message(scan_f_illegal_char);
  1645.                                    while c in ['0'..'9'] do
  1646.                                      begin
  1647.                                         pattern:=pattern+c;
  1648.                                         nextchar;
  1649.                                      end;
  1650.                                 end;
  1651.                               yylex:=REALNUMBER;
  1652.                               goto yylex_exit;
  1653.                            end;
  1654.                          yylex:=INTCONST;
  1655.                          goto yylex_exit;
  1656.                       end;
  1657.            ';'      : begin
  1658.                          nextchar;
  1659.                          yylex:=SEMICOLON;
  1660.                          exit;
  1661.                       end;
  1662.            '['      : begin
  1663.                          nextchar;
  1664.                          yylex:=LECKKLAMMER;
  1665.                          goto yylex_exit;
  1666.                       end;
  1667.            ']'      : begin
  1668.                          nextchar;
  1669.                          yylex:=RECKKLAMMER;
  1670.                          goto yylex_exit;
  1671.                       end;
  1672.            '('      : begin
  1673.                          nextchar;
  1674.                          if c='*' then
  1675.                            begin
  1676.                               inc(comment_level);
  1677.                               nextchar;
  1678.                               while true do
  1679.                                 begin
  1680.                                    { this is currently not supported }
  1681.                                    if c='$' then
  1682.                                     Message(scan_e_wrong_styled_switch);
  1683.                                    repeat
  1684.                                       while c<>'*' do
  1685.                                         begin
  1686.                                            if c=#26 then Message(scan_f_end_of_file);
  1687. {                                           if c=newline then write_line;}
  1688.                                            nextchar;
  1689.                                         end;
  1690.                                       if c=#26 then Message(scan_f_end_of_file);
  1691.                                       {if c=newline then write_line;}
  1692.                                       nextchar;
  1693.                                    until c=')';
  1694.                                    dec(comment_level);
  1695.  
  1696.                                    nextchar;
  1697.                                    { check for *)(* }
  1698.                                    if c='(' then
  1699.                                      begin
  1700.                                         nextchar;
  1701.                                         if c<>'*' then
  1702.                                           begin
  1703.                                              yylex:=LKLAMMER;
  1704.                                              goto yylex_exit;
  1705.                                           end;
  1706.                                         inc(comment_level);
  1707.                                         nextchar;
  1708.                                      end
  1709.                                    else
  1710.                                      begin
  1711. {$ifndef TP}
  1712.                                         yylex:=yylex();
  1713. {$else TP}
  1714.                                         yylex:=yylex;
  1715. {$endif TP}
  1716.                                         goto yylex_exit;
  1717.                                      end;
  1718.                                 end;
  1719.                            end;
  1720.                          yylex:=LKLAMMER;
  1721.                          goto yylex_exit;
  1722.                       end;
  1723.  
  1724.            ')'      : begin
  1725.                          nextchar;
  1726.                          yylex:=RKLAMMER;
  1727.                          goto yylex_exit;
  1728.                       end;
  1729.            '+'      : begin
  1730.                          nextchar;
  1731.                          if (c='=') and c_like_operators then
  1732.                            begin
  1733.                               nextchar;
  1734.                               yylex:=_PLUSASN;
  1735.                               goto yylex_exit;
  1736.                            end
  1737.                          else
  1738.                            begin
  1739.                               yylex:=PLUS;
  1740.                               goto yylex_exit;
  1741.                            end;
  1742.                       end;
  1743.            '-'      : begin
  1744.                          nextchar;
  1745.                          if (c='=') and c_like_operators then
  1746.                            begin
  1747.                               nextchar;
  1748.                               yylex:=_MINUSASN;
  1749.                               goto yylex_exit;
  1750.                            end
  1751.                          else
  1752.                            begin
  1753.                               yylex:=MINUS;
  1754.                               goto yylex_exit;
  1755.                            end;
  1756.                       end;
  1757.            ':'      : begin
  1758.                          nextchar;
  1759.                          if c='=' then
  1760.                            begin
  1761.                               nextchar;
  1762.                               yylex:=ASSIGNMENT;
  1763.                               goto yylex_exit;
  1764.                            end
  1765.                          else
  1766.                            begin
  1767.                               yylex:=COLON;
  1768.                               goto yylex_exit;
  1769.                            end;
  1770.                       end;
  1771.            '*'      : begin
  1772.                          nextchar;
  1773.                          if (c='=') and c_like_operators then
  1774.                            begin
  1775.                               nextchar;
  1776.                               yylex:=_STARASN;
  1777.                               goto yylex_exit;
  1778.                            end
  1779.                          else
  1780.                            begin
  1781.                               yylex:=STAR;
  1782.                               goto yylex_exit;
  1783.                            end;
  1784.                       end;
  1785.            '/'      : begin
  1786.                          nextchar;
  1787.                          if (c='=') and c_like_operators then
  1788.                            begin
  1789.                               nextchar;
  1790.                               yylex:=_SLASHASN;
  1791.                               goto yylex_exit;
  1792.                            end
  1793.                          else if (c='/') then
  1794.                            begin
  1795.                               delphi_comment;
  1796. {$ifndef TP}
  1797.                               yylex:=yylex();
  1798. {$else TP}
  1799.                               yylex:=yylex;
  1800. {$endif TP}
  1801.                               goto yylex_exit;
  1802.                            end
  1803.                          else
  1804.                            begin
  1805.                               yylex:=SLASH;
  1806.                               goto yylex_exit;
  1807.                            end;
  1808.                       end;
  1809.            '='      : begin
  1810.                          nextchar;
  1811.                          yylex:=EQUAL;
  1812.                          goto yylex_exit;
  1813.                       end;
  1814.            '.'      : begin
  1815.                          nextchar;
  1816.                          if c='.' then
  1817.                            begin
  1818.                               nextchar;
  1819.                               yylex:=POINTPOINT;
  1820.                               goto yylex_exit;
  1821.                            end
  1822.                          else
  1823.                          yylex:=POINT;
  1824.                          goto yylex_exit;
  1825.                       end;
  1826.            '@'      : begin
  1827.                          nextchar;
  1828.                          if c='@' then
  1829.                            begin
  1830.                               nextchar;
  1831.                               yylex:=DOUBLEADDR;
  1832.                            end
  1833.                          else
  1834.                            yylex:=KLAMMERAFFE;
  1835.                          goto yylex_exit;
  1836.                       end;
  1837.            ','      : begin
  1838.                          nextchar;
  1839.                          yylex:=COMMA;
  1840.                          exit;
  1841.                       end;
  1842.            '''','#','^' :
  1843.                       begin
  1844.                          if c='^' then
  1845.                            begin
  1846.                               nextchar;
  1847.                               c:=upcase(c);
  1848.                               if not(parse_types) and (c in ['A'..'Z']) then
  1849.                                 begin
  1850.                                    pattern:=chr(ord(c)-64);
  1851.                                    nextchar;
  1852.                                 end
  1853.                               else
  1854.                                 begin
  1855.                                    yylex:=CARET;
  1856.                                    goto yylex_exit;
  1857.                                 end;
  1858.                            end
  1859.                          else pattern:='';
  1860.                          while true do
  1861.                            case c of
  1862.                              '#' :
  1863.                                 begin
  1864.                                    hs:='';
  1865.                                    nextchar;
  1866.                                    if c='$' then
  1867.                                      begin
  1868.                                         hs:='$';
  1869.                                         nextchar;
  1870.                                         while c in (['0'..'9','a'..'f','A'..'F']) do
  1871.                                           begin
  1872.                                              hs:=hs+upcase(c);
  1873.                                              nextchar;
  1874.                                           end;
  1875.                                      end
  1876.                                    else
  1877.                                    { FPC supports binary constants }
  1878.                                    { %10101 evalutes to 37         }
  1879.                                    if c='%' then
  1880.                                      begin
  1881.                                         nextchar;
  1882.                                         while c in ['0','1'] do
  1883.                                           begin
  1884.                                              hs:=hs+upcase(c);
  1885.                                              nextchar;
  1886.                                           end;
  1887.                                      end
  1888.                                    else
  1889.                                      begin
  1890.                                         while (ord(c)>=ord('0')) and (ord(c)<=ord('9')) do
  1891.                                           begin
  1892.                                              hs:=hs+c;
  1893.                                              nextchar;
  1894.                                           end;
  1895.                                      end;
  1896.                                    valint(hs,l,code);
  1897.                                    if (code<>0) or (l<0) or (l>255) then
  1898.                                      Message(scan_e_illegal_char_const);
  1899.                                     pattern:=pattern+chr(l);
  1900.                                  end;
  1901.                              '''' :
  1902.                                 begin
  1903.                                    repeat
  1904.                                      nextchar;
  1905.                      case c of
  1906.                        #26 : begin
  1907.                                Message(scan_f_end_of_file);
  1908.                                break;
  1909.                              end;
  1910.                        #13,
  1911.                                newline : begin
  1912.                                             Message(scan_f_string_exceeds_line);
  1913.                                             break;
  1914.                                          end;
  1915.                        '''' : begin
  1916.                                   nextchar;
  1917.                                   if c<>'''' then
  1918.                                       break;
  1919.                               end;
  1920.                    end;
  1921.                                      pattern:=pattern+c;
  1922.                                    until false;
  1923.                                 end;
  1924.                              '^' : begin
  1925.                                       nextchar;
  1926.                                       c:=upcase(c);
  1927.                                       if c in ['A'..'Z'] then
  1928.                                         pattern:=pattern+chr(ord(c)-64)
  1929.                                       else Message(scan_f_illegal_char);
  1930.                                       nextchar;
  1931.                                    end;
  1932.                              else break;
  1933.                            end;
  1934.                          { strings with length 1 become const chars }
  1935.                          if length(pattern)=1 then
  1936.                            yylex:=CCHAR
  1937.                            else yylex:=CSTRING;
  1938.                          goto yylex_exit;
  1939.                       end;
  1940.            '>'      : begin
  1941.                          nextchar;
  1942.                          if c='=' then
  1943.                            begin
  1944.                               nextchar;
  1945.                               yylex:=GTE;
  1946.                               goto yylex_exit;
  1947.                            end
  1948.                          else if c='>' then
  1949.                            begin
  1950.                               nextchar;
  1951.                               yylex:=_SHR;
  1952.                               goto yylex_exit;
  1953.                            end
  1954.                          else if c='<' then
  1955.                            begin
  1956.                               nextchar;
  1957.                               { >< is for a symetric diff for sets }
  1958.                               yylex:=SYMDIF;
  1959.                               goto yylex_exit;
  1960.                            end
  1961.                          else
  1962.                            begin
  1963.                               yylex:=GT;
  1964.                               goto yylex_exit;
  1965.                            end;
  1966.                       end;
  1967.            '<'      : begin
  1968.                          nextchar;
  1969.                          if c='>' then
  1970.                            begin
  1971.                               nextchar;
  1972.                               yylex:=UNEQUAL;
  1973.                               goto yylex_exit;
  1974.                            end
  1975.                          else if c='=' then
  1976.                            begin
  1977.                               nextchar;
  1978.                               yylex:=LTE;
  1979.                               goto yylex_exit;
  1980.                            end
  1981.                          else if c='<' then
  1982.                            begin
  1983.                               nextchar;
  1984.                               yylex:=_SHL;
  1985.                               goto yylex_exit;
  1986.                            end
  1987.                          else
  1988.                            begin
  1989.                               yylex:=LT;
  1990.                               goto yylex_exit;
  1991.                            end;
  1992.                       end;
  1993.            #26      : begin
  1994.                          yylex:=_EOF;
  1995.                          goto yylex_exit;
  1996.                       end;
  1997.            else
  1998.              begin
  1999.                 update_line;
  2000.                 Message(scan_f_illegal_char);
  2001.              end;
  2002.            end;
  2003.      yylex_exit :
  2004.         update_line;
  2005.      end;
  2006.  
  2007.     const last_asmgetchar_was_a_comment : boolean = false;
  2008.  
  2009.     function asmgetchar : char;
  2010.       begin
  2011.          if c='{' then
  2012.            begin
  2013.               src_comment;
  2014.               { a comment is a seperator }
  2015.               asmgetchar:=';';
  2016.               last_asmgetchar_was_a_comment:=true;
  2017.            end
  2018.          else
  2019.            begin
  2020.               update_line;
  2021.               if last_asmgetchar_was_a_comment then
  2022.                 begin
  2023.                    last_asmgetchar_was_a_comment:=false;
  2024.                    asmgetchar:=c;
  2025.                    exit;
  2026.                 end;
  2027.               nextchar;
  2028.               asmgetchar:=c;
  2029.               if c='/' then
  2030.                begin
  2031.                  nextchar;
  2032.                  if c='/' then
  2033.                   begin
  2034.                     delphi_comment;
  2035.                     asmgetchar:=c;
  2036.                   end
  2037.                  else
  2038.                   begin
  2039.                     last_asmgetchar_was_a_comment:=true;
  2040.                     asmgetchar:='/';
  2041.                   end;
  2042.                end;
  2043.            end;
  2044.       end;
  2045.  
  2046.    procedure initscanner(const fn: string);
  2047.      var
  2048.        d:dirstr;
  2049.        n:namestr;
  2050.        e:extstr;
  2051.      begin
  2052.         fsplit(fn,d,n,e);
  2053.  
  2054.         current_module^.current_inputfile:=new(pinputfile,init(d,n,e));
  2055.         current_module^.current_inputfile^.reset;
  2056.  
  2057.         current_module^.sourcefiles.register_file(current_module^.current_inputfile);
  2058.  
  2059.         if ioresult<>0 then
  2060.          Message(scan_f_cannot_open_input);
  2061.  
  2062.         inputbuffer:=current_module^.current_inputfile^.buf;
  2063.         preprocstack:=nil;
  2064.         reload;
  2065.         comment_level:=0;
  2066.         lasttokenpos:=0;
  2067.         lastlinepointer:=0;
  2068.         s_point:=false;
  2069.      end;
  2070.  
  2071.    procedure donescanner(compiled_at_higher_level : boolean);
  2072.  
  2073.      var
  2074.         st : string;
  2075.  
  2076.      begin
  2077.         if not (compiled_at_higher_level) and  assigned(preprocstack) then
  2078.           begin
  2079.              if preprocstack^.t=PP_IFDEF then
  2080.                st:='$IF(N)(DEF)'
  2081.              else
  2082.                st:='$ELSE';
  2083.              Message3(scan_e_endif_expected,st,preprocstack^.name,tostr(preprocstack^.line_nb));
  2084.           end;
  2085.      end;
  2086.  
  2087. end.
  2088. {
  2089.   $Log: scanner.pas,v $
  2090.   Revision 1.3  1998/03/29 17:27:59  florian
  2091.     * aopt386 compiles with TP
  2092.     * correct line number is displayed, if a #0 is in the input
  2093.  
  2094.   Revision 1.2  1998/03/28 23:09:57  florian
  2095.     * secondin bugfix (m68k and i386)
  2096.     * overflow checking bugfix (m68k and i386) -- pretty useless in
  2097.       secondadd, since everything is done using 32-bit
  2098.     * loading pointer to routines hopefully fixed (m68k)
  2099.     * flags problem with calls to RTL internal routines fixed (still strcmp
  2100.       to fix) (m68k)
  2101.     * #ELSE was still incorrect (didn't take care of the previous level)
  2102.     * problem with filenames in the command line solved
  2103.     * problem with mangledname solved
  2104.     * linking name problem solved (was case insensitive)
  2105.     * double id problem and potential crash solved
  2106.     * stop after first error
  2107.     * and=>test problem removed
  2108.     * correct read for all float types
  2109.     * 2 sigsegv fixes and a cosmetic fix for Internal Error
  2110.     * push/pop is now correct optimized (=> mov (%esp),reg)
  2111.  
  2112.   Revision 1.1.1.1  1998/03/25 11:18:15  root
  2113.   * Restored version
  2114.  
  2115.   Revision 1.43  1998/03/24 21:48:34  florian
  2116.     * just a couple of fixes applied:
  2117.          - problem with fixed16 solved
  2118.          - internalerror 10005 problem fixed
  2119.          - patch for assembler reading
  2120.          - small optimizer fix
  2121.          - mem is now supported
  2122.  
  2123.   Revision 1.42  1998/03/10 17:19:29  peter
  2124.     * fixed bug0108
  2125.     * better linebreak scanning (concentrated in nextchar(), it supports
  2126.       #10, #13, #10#13, #13#10
  2127.  
  2128.   Revision 1.41  1998/03/10 16:27:45  pierre
  2129.     * better line info in stabs debug
  2130.     * symtabletype and lexlevel separated into two fields of tsymtable
  2131.     + ifdef MAKELIB for direct library output, not complete
  2132.     + ifdef CHAINPROCSYMS for overloaded seach across units, not fully
  2133.       working
  2134.     + ifdef TESTFUNCRET for setting func result in underfunction, not
  2135.       working
  2136.  
  2137.   Revision 1.40  1998/03/10 01:17:27  peter
  2138.     * all files have the same header
  2139.     * messages are fully implemented, EXTDEBUG uses Comment()
  2140.     + AG... files for the Assembler generation
  2141.  
  2142.   Revision 1.39  1998/03/09 12:58:14  peter
  2143.     * FWait warning is only showed for Go32V2 and $E+
  2144.     * opcode tables moved to i386.pas/m68k.pas to reduce circular uses (and
  2145.       for m68k the same tables are removed)
  2146.     + $E for i386
  2147.  
  2148.   Revision 1.38  1998/03/06 00:52:52  peter
  2149.     * replaced all old messages from errore.msg, only ExtDebug and some
  2150.       Comment() calls are left
  2151.     * fixed options.pas
  2152.  
  2153.   Revision 1.37  1998/03/04 17:34:06  michael
  2154.   + Changed ifdef FPK to ifdef FPC
  2155.  
  2156.   Revision 1.36  1998/03/03 22:38:34  peter
  2157.     * the last 3 files
  2158.  
  2159.   Revision 1.35  1998/03/02 01:49:26  peter
  2160.     * renamed target_DOS to target_GO32V1
  2161.     + new verbose system, merged old errors and verbose units into one new
  2162.       verbose.pas, so errors.pas is obsolete
  2163.  
  2164.   Revision 1.34  1998/02/26 11:57:16  daniel
  2165.   * New assembler optimizations commented out, because of bugs.
  2166.   * Use of dir-/name- and extstr.
  2167.  
  2168.   Revision 1.33  1998/02/22 23:03:32  peter
  2169.     * renamed msource->mainsource and name->unitname
  2170.     * optimized filename handling, filename is not seperate anymore with
  2171.       path+name+ext, this saves stackspace and a lot of fsplit()'s
  2172.     * recompiling of some units in libraries fixed
  2173.     * shared libraries are working again
  2174.     + $LINKLIB <lib> to support automatic linking to libraries
  2175.     + libraries are saved/read from the ppufile, also allows more libraries
  2176.       per ppufile
  2177.  
  2178.   Revision 1.32  1998/02/17 21:20:59  peter
  2179.     + Script unit
  2180.     + __EXIT is called again to exit a program
  2181.     - target_info.link/assembler calls
  2182.     * linking works again for dos
  2183.     * optimized a few filehandling functions
  2184.     * fixed stabs generation for procedures
  2185.  
  2186.   Revision 1.31  1998/02/16 12:51:44  michael
  2187.   + Implemented linker object
  2188.  
  2189.   Revision 1.30  1998/02/13 10:35:45  daniel
  2190.   * Made Motorola version compilable.
  2191.   * Fixed optimizer
  2192.  
  2193.   Revision 1.29  1998/02/12 17:19:25  florian
  2194.     * fixed to get remake3 work, but needs additional fixes (output, I don't like
  2195.       also that aktswitches isn't a pointer)
  2196.  
  2197.   Revision 1.28  1998/02/12 11:50:44  daniel
  2198.   Yes! Finally! After three retries, my patch!
  2199.  
  2200.   Changes:
  2201.  
  2202.   Complete rewrite of psub.pas.
  2203.   Added support for DLL's.
  2204.   Compiler requires less memory.
  2205.   Platform units for each platform.
  2206.  
  2207.   Revision 1.27  1998/02/07 09:39:27  florian
  2208.     * correct handling of in_main
  2209.     + $D,$T,$X,$V like tp
  2210.  
  2211.   Revision 1.26  1998/02/05 22:27:06  florian
  2212.     * small problems fixed: remake3 should now work
  2213.  
  2214.   Revision 1.25  1998/02/03 22:13:35  florian
  2215.     * clean up
  2216.  
  2217.   Revision 1.24  1998/02/02 23:42:38  florian
  2218.     * data is now dword aligned per default else the stack ajustements are useless
  2219.     + $wait directive: stops compiling til return is presseed (a message is
  2220.       also written, useful to give the user a change to notice a message
  2221.  
  2222.   Revision 1.23  1998/02/02 13:13:28  pierre
  2223.     * line_count transfered to tinputfile, to avoid crosscounting
  2224.  
  2225.   Revision 1.22  1998/01/30 17:30:10  pierre
  2226.     + better line counting mechanism
  2227.       line count updated only when important tokens are read
  2228.       (not for comment , ; )
  2229.  
  2230.   Revision 1.21  1998/01/26 19:09:52  peter
  2231.     * fixed EOF in open string constant reading
  2232.  
  2233.   Revision 1.20  1998/01/22 08:56:55  peter
  2234.     * Fixed string exceeds end of line problem (#13 is not a linux
  2235.       linebreak)
  2236.  
  2237.   Revision 1.19  1998/01/20 18:18:46  peter
  2238.     * fixed skip_until_pragma, bug0044 and the compiler recompile good
  2239.  
  2240.   Revision 1.18  1998/01/20 16:30:17  pierre
  2241.     * bug with braces in log from Peter removed
  2242.  
  2243.   Revision 1.17  1998/01/20 15:14:33  peter
  2244.     * fixes bug 44 with multiple $'s between skipped $IFDEF and $ENDIF
  2245.  
  2246.   Revision 1.16  1998/01/13 16:16:06  pierre
  2247.     *  bug in interdependent units handling
  2248.        - primary unit was not in loaded_units list
  2249.        - current_module^.symtable was assigned too early
  2250.        - donescanner must not call error if the compilation
  2251.        of the unit was done at a higher level.
  2252.  
  2253.   Revision 1.15  1998/01/09 23:08:34  florian
  2254.     + C++/Delphi styled //-comments
  2255.     * some bugs in Delphi object model fixed
  2256.     + override directive
  2257.  
  2258.   Revision 1.14  1998/01/09 18:01:17  florian
  2259.     * VIRTUAL isn't anymore a common keyword
  2260.     + DYNAMIC is equal to VIRTUAL
  2261.  
  2262.   Revision 1.13  1998/01/09 13:39:57  florian
  2263.     * public, protected and private aren't anymore key words
  2264.     + published is equal to public
  2265.  
  2266.   Revision 1.12  1997/12/12 13:28:41  florian
  2267.   + version 0.99.0
  2268.   * all WASM options changed into MASM
  2269.   + -O2 for Pentium II optimizations
  2270.  
  2271.   Revision 1.11  1997/12/10 23:07:30  florian
  2272.   * bugs fixed: 12,38 (also m68k),39,40,41
  2273.   + warning if a system unit is without -Us compiled
  2274.   + warning if a method is virtual and private (was an error)
  2275.   * some indentions changed
  2276.   + factor does a better error recovering (omit some crashes)
  2277.   + problem with @type(x) removed (crashed the compiler)
  2278.  
  2279.   Revision 1.10  1997/12/09 14:09:15  carl
  2280.   * bugfix of Runerror 216 when reading a null character (such as trying to
  2281.     compile a binary file)
  2282.  
  2283.   Revision 1.9  1997/12/08 11:51:12  pierre
  2284.     * corrected some buggy code in hexadecimal number reading
  2285.  
  2286.   Revision 1.8  1997/12/05 14:22:20  daniel
  2287.   * Did some source code beutification.
  2288.  
  2289.   Revision 1.7  1997/12/03 13:43:14  carl
  2290.   + OUTPUT_FORMAT switch is processor specific to i386.
  2291.  
  2292.   Revision 1.6  1997/12/02 16:00:55  carl
  2293.   * bugfix of include files - now gives out a fatalerror if not found,
  2294.   otherwise would create invalid pointer operations everywhere.
  2295.   * bugfix of $i+xyz now the $i+/- switch is correctly recognized as io
  2296.   checking and ont an include directive.
  2297.  
  2298.   Revision 1.5  1997/11/28 18:14:48  pierre
  2299.    working version with several bug fixes
  2300.  
  2301.   Revision 1.4  1997/11/28 14:26:26  florian
  2302.   Fixed some bugs
  2303.  
  2304.   Revision 1.3  1997/11/27 17:47:14  carl
  2305.   * fixed bug with assem switches and m68k.
  2306.  
  2307.   Revision 1.2  1997/11/27 17:40:48  carl
  2308.   + assem type scanning switches for intel targets.
  2309.  
  2310.   Revision 1.1.1.1  1997/11/27 08:33:01  michael
  2311.   FPC Compiler CVS start
  2312.  
  2313.   Pre-CVS log:
  2314.  
  2315.   CEC    Carl-Eric Codere
  2316.   FK     Florian Klaempfl
  2317.   PM     Pierre Muller
  2318.   +      feature added
  2319.   -      removed
  2320.   *      bug fixed or changed
  2321.  
  2322.   History:
  2323.        6th september 1997:
  2324.          + added support for global switches (i.e $X and $E (for m68k)) (CEC)
  2325.        1st october 1997:
  2326.          + added $ifopt as dummy which is always rejected (FK)
  2327.       13th october 1997:
  2328.          * user defined message are now written via the errors unit
  2329.            and exterror (FK)
  2330.          + compiler switch $INFO added, does the same like $MESSAGE,
  2331.            the text is written via comment(v_info,...) (FK)
  2332.          + $STOP and $FATALERROR added: they are equivalent, the
  2333.            following message is written and the compiler stops (FK)
  2334.          - write_c, no more necessary (FK)
  2335.       14th october 1997:
  2336.          + wrong line counting corrected: <comment start> $I test
  2337.                                           <comment end>
  2338.            (FK)
  2339.       17th october 1997:
  2340.          + support of $if expr   (FK)
  2341.          * $define a=1234 to a:=1234   (FK)
  2342.          + -So allows now <comment start> <comment start> <comment end>
  2343.            as comment (preocedure dec_comment_level)    (FK)
  2344.       22th october 1997:
  2345.          + $NOTE  (FK)
  2346.        9th november 1997:
  2347.           + added updating of line_no in asmgetchar. (CEC)
  2348.       14th november 1997:
  2349.           * fixed problem with asm line counting. (CEC)
  2350.       17th november 1997:
  2351.          + kommentar renamed src_comment and kommentarebene renamed comment_level (PM)
  2352.  
  2353. }
  2354.  
  2355.